#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#define PORT 8080
struct pthread_param
{
  int* socket_desc;
  struct sockaddr_in* addr;
};
void *connection_handler(void *);

int main() {
    int sockfd, newsockfd;
    struct sockaddr_in serv_addr, cli_addr;
    socklen_t clilen;
    pthread_t thread_id;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("ERROR opening socket");
        exit(1);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(PORT);

    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        perror("ERROR on binding");
        exit(1);
    }

    listen(sockfd, 5);
    clilen = sizeof(cli_addr);
    while (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) {
        struct pthread_param param;
        param.addr = &cli_addr;
        param.socket_desc = &newsockfd;
        if (pthread_create(&thread_id, NULL, connection_handler, (void*)&param) < 0) {
            perror("ERROR on thread creation");
            return 1;
        }
        //printf("HERE1\n");
    }

    if (newsockfd < 0) {
        perror("ERROR on accept");
        exit(1);
    }
    printf("return\n");
    close(sockfd);
    return 0;
}

void *connection_handler(void *pparam) {
    struct pthread_param param = *(struct pthread_param*)pparam;
    int sock = *(param.socket_desc);
    struct sockaddr_in cli_addr = *(param.addr);
    char buffer[256];
    char bufferOut[512];
    char clientId[256] = "test";
	//printf("heer\n");
    bzero(buffer, 256);
    bzero(bufferOut, 512);
    bzero(clientId, 256);    
    //printf("hear\n");
    sprintf(clientId, "Client IP: %s, Port: %d",inet_ntop(AF_INET, &(cli_addr.sin_addr.s_addr), buffer, sizeof(buffer)), ntohs(cli_addr.sin_port));
    //printf("here1\n");
    printf("[Conect] Thread: %d, %s\n", getpid(), clientId);
   // printf("here2\n");
    bzero(buffer, 256);
    strcpy(buffer, "Hello, this is server\nNow you can talk to me continuesly while I will repeat what you say to you.\n");
    strcat(buffer, "When you want to exit, tell me \"stop\"\n");
    //write(sock, buffer, strlen(buffer));
    send(sock, buffer, sizeof(buffer), 0);  
    while(strcmp("stop\n", buffer) != 0){
        bzero(buffer, 256);
        //read(sock, buffer, 255);
        recv(sock, buffer, sizeof(buffer), 0);
        printf("[Receive from %s]: %s\n", clientId, buffer);

        sprintf(bufferOut, "Server has received: %s", buffer);
        printf("[Send to %s]: %s\n", clientId, bufferOut);
        send(sock, bufferOut, sizeof(bufferOut), 0);
        //write(sock, bufferOut, strlen(bufferOut));    
    }
    printf("[Closer] %s\n", clientId);
    close(sock);
    return 0;
}
